package com;

public class
证明CPU乱序执行 {
    private static int x = 0, y = 0;
    private static int a = 0, b = 0;

    /**
     * 在我们的Java虚拟机执行代码的时候，需要从缓存中读取数据，这个时候CPU是空闲状态，为了防止浪费CPU性能，所以
     * 让CPU在读取缓存的时间里面先执行其它与现在读取的缓存不相关的代码，这个在我们的代码中叫做乱序执行，以下代码
     * 是为了证明我们的CPU确实发生乱序执行的代码
     * 注意：我们的volatile关键字可以保证我们的变量的
     *      有序性:禁止重排序
     *      可见性:指当多个线程访问同一个变量时，一个线程修改了这个变量的值，其他线程能够立即看得到修改的值
     *      原子性:即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断，要么就都不执行。
     */
    public static void main(String[] args) throws InterruptedException {
        int i = 0;
        while (true){
            i++;
            x=0; y=0; a=0; b=0;
            // 用来计算两个线程之间差距大概多少微妙
            // final long[] start = {0};
            Thread one = new Thread(new Runnable() {
                public void run() {
                    // 由于线程one先启动，下面这句话让它等一等线程two，读者可以根据自己电脑实际性能适当调整等待时间
                    shortWait(30000);
                    // start[0] =System.nanoTime();
                    a = 1;
                    x = b;
                }
            });
            Thread two = new Thread(new Runnable() {
                public void run() {
                    // System.out.println(System.nanoTime() - start[0]);
                    b = 1;
                    y = a;
                }
            });
            /**
             * 如果代码没有重排序，那么有三种可能
             * 1、a=1;x=b;b=1;y=a;   ==>   x=0,y=1;
             * 2、b=1,y=a;a=1;x=b;   ==>   x=1,y=0;
             * 3、a=1;b=1;y=a;x=b;   ==>   x=1,y=1
             * 在所有的可能性中不可能出现 x=0,y=0的情况
             * 所以如果出现x=0,y=0则表示我们的CPU确实是乱序执行的
             */
            one.start();two.start();
            one.join();two.join();
            String result = "第"+i+"次("+x+","+y+")";
            System.out.println(result);
            if (x==0&&y==0){
                break;
            }
        }
    }

    /**
     * 设置等待一定微妙的方法
     */
    public static void shortWait(long interval){
        long start = System.nanoTime();
        long end;
        do {
            end = System.nanoTime();
        }while (start+interval >= end);
    }
}
